package com.ccExcelUtil.checkExcel;
import com.ccExcelUtil.util.ExcelUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

import static com.ccExcelUtil.constant.GlobalConstant.*;

/**
 * @author <a href="mailto:"校验excel数据
 * @author xiaozhao
 * @date 2024/03/08
 */
@SuppressWarnings("unchecked")
public class CheckExcelUtil {

    /**
     * 本地文件校验并输出到指定位置
     *
     * @param filePath   本地文件路径
     * @param t          校验实体
     * @param toFilePath 输出的文件路径
     * @param <T>        校验实体
     * @return 校验成功后的数据集
     */
    public static <T> List<T> checkExcelData(String filePath, Class<T> t, String toFilePath) {
        InputStream inputStream;
        try {
            inputStream = Files.newInputStream(Paths.get(filePath));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Map<String, Object> map = ExcelUtils.readData(inputStream, t);
        return ExcelUtils.writeToXssList(toFilePath, map);
    }


    /**
     * 本地文件校验并输出到web
     *
     * @param inputStream 本地文件输入流
     * @param t           校验实体
     * @param <T>         校验实体
     * @return 校验成功后的输出流
     */
    public static <T> InputStream checkExcelDataToWeb(InputStream inputStream, Class<T> t) {
        Map<String, Object> map = ExcelUtils.readData(inputStream, t);
        return ExcelUtils.writeToWeb(map);
    }

    /**
     * 本地文件校验，校验成功返回所有数据
     *
     * @param inputStream 校验文件的输入流
     * @param t           校验实体
     * @param <T>         校验实体
     * @return 校验成功返回所有数据，校验失败返回空
     */
    public static <T> List<T> checkExcelData(InputStream inputStream, Class<T> t) {
        Map<String, Object> map = ExcelUtils.readData(inputStream, t);
        boolean res = (Boolean) map.get(RES);
        return res ? Collections.emptyList() : (List<T>) map.get(DATA);
    }

    /**
     * 本地文件校验，并指定模版返回
     *
     * @param filePath         本地文件路径
     * @param t                校验实体
     * @param row              从多少行开始校验
     * @param templateFilePath 校验返回模版
     * @param toFilePath       输出文件地址
     * @param <T>              校验实体
     * @return 校验成功返回所有数据
     */
    public static <T> List<T> checkExcelData(String filePath, Class<T> t, int row, String templateFilePath, String toFilePath) {
        Map<String, Object> map;
        try {
            map = ExcelUtils.readData(Files.newInputStream(Paths.get(filePath)), t, row, Files.newInputStream(Paths.get(templateFilePath)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ExcelUtils.writeToXssList(toFilePath, map);
    }


    /**
     * 本地文件校验，并指定模版返回
     *
     * @param inputStream         本地文件输入流
     * @param t                   校验实体
     * @param row                 从多少行开始校验
     * @param templateInputStream 校验模版输入流
     * @param <T>                 校验实体
     * @return 校验成功返回所有流
     */
    public static <T> InputStream checkExcelDataToWeb(InputStream inputStream, Class<T> t, int row, InputStream templateInputStream) {
        Map<String, Object> map = ExcelUtils.readData(inputStream, t, row, templateInputStream);
        return ExcelUtils.writeToWeb(map);
    }


    /**
     * 多sheet校验
     *
     * @param inputStream 输入流
     * @param toFilePath  输出文件地址
     * @param classes     校验实体集合
     * @return 校验成功后的数据集合
     */
    public static Map<Integer, List<Object>> checkExcelAllSheet(InputStream inputStream, String toFilePath, Class<?>... classes) {
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();
        Map<Integer, Class<?>> map = new HashMap<>();
        for (int i = 0; i < classes.length; i++) {
            map.put(i, classes[i]);
        }
        Map<String, Object> resultMap = ExcelUtils.readSheet(inputStream, map, sxssfWorkbook);
        return ExcelUtils.writeToXssMap(toFilePath, resultMap);
    }

    /**
     * 多sheet模版校验
     * @param inputStream
     * @param templateInputStream
     * @param toFilePath
     * @param rows
     * @param classes
     * @return
     */
    public static Map<Integer, List<Object>> checkExcelAllSheet(InputStream inputStream, InputStream templateInputStream,String toFilePath, Integer[] rows,Class<?>[] classes) {
        if(rows.length!=classes.length){
            throw new IllegalArgumentException("rows and classes array length not match.");
        }
        Map<Integer, Class<?>> map = new HashMap<>();
        for (int i = 0; i < classes.length; i++) {
            map.put(i, classes[i]);
        }
        XSSFWorkbook xwb;
        try {
            xwb  = new XSSFWorkbook(templateInputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xwb);
        Map<String, Object> resultMap = ExcelUtils.readSheet(inputStream, map, rows,sxssfWorkbook);
        return ExcelUtils.writeToXssMap(toFilePath, resultMap);
    }

    /**
     * 多sheet校验
     *
     * @param inputStream 输入流
     * @param classes     校验实体集合
     * @return 校验成功后的输入流
     */
    public static InputStream checkExcelAllSheetToWeb(InputStream inputStream, Class<?>... classes) {
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();
        Map<Integer, Class<?>> map = new HashMap<>();
        for (int i = 0; i < classes.length; i++) {
            map.put(i, classes[i]);
        }
        Map<String, Object> resultMap = ExcelUtils.readSheet(inputStream, map, sxssfWorkbook);
        return ExcelUtils.writeToWeb(resultMap);
    }

    /**
     * 多sheet模版校验web
     * @param inputStream
     * @param templateInputStream
     * @param rows
     * @param classes
     * @return
     */
    public static InputStream checkExcelAllSheetToWeb(InputStream inputStream, InputStream templateInputStream,Integer[] rows,Class<?>[] classes){
        if(rows.length!=classes.length){
            throw new IllegalArgumentException("rows and classes array length not match.");
        }
        Map<Integer, Class<?>> map = new HashMap<>();
        for (int i = 0; i < classes.length; i++) {
            map.put(i, classes[i]);
        }
        XSSFWorkbook xwb;
        try {
            xwb  = new XSSFWorkbook(templateInputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(xwb);
        Map<String, Object> resultMap = ExcelUtils.readSheet(inputStream, map, rows,sxssfWorkbook);
        return ExcelUtils.writeToWeb(resultMap);
    }

    /**
     * 从本地得到多个sheet的数据
     * @param filePath
     * @param classes
     * @return
     */
    public static Map<Integer, List<?>> getMultiSheetData(String filePath, Class<?>... classes) {
        try {
            FileInputStream fileInputStream = new FileInputStream(filePath);
            List<Class<?>> list = new ArrayList<>(Arrays.asList(classes));
            return ExcelUtils.getMultiSheetData(fileInputStream, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 得到多个sheet的数据输入流
     * @param inputStream
     * @param classes
     * @return
     */
    public static Map<Integer, List<?>> getMultiSheetData(InputStream inputStream, Class<?>... classes) {
        try {
            List<Class<?>> list = new ArrayList<>(Arrays.asList(classes));
            return ExcelUtils.getMultiSheetData(inputStream, list);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param filePath
     * @param t
     * @param <T>
     * @return
     */
    public static <T> List<T> getData(String filePath, Class<T> t) {
        try {
            FileInputStream fileInputStream = new FileInputStream(filePath);
            return ExcelUtils.getData(fileInputStream, t);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
